#pragma once
#include "output.hpp"

namespace my_log
{
    // 次级建造者抽象基类
	class builder_base
	{
	public:
		// 抽象建造函数
		virtual output_t build() = 0;

		// 抽象文件名更改函数
		virtual void changeName(const std::filesystem::path&) = 0;
	};

	// 次级建造者模板类
	template<typename T>
	requires std::derived_from<T, output_base<T>>
	class output_builder : public builder_base
	{};

	// 实例化次级建造者类
	template<>
	class output_builder<screen_output> : public builder_base
	{
	public:
		// 返回显示器输出类
		virtual output_t build();
	private:
		// 已弃用
		virtual void changeName(const std::filesystem::path&);
	};

	// 实例化次级建造者类
	template<>
	class output_builder<file_output> : public builder_base
	{
	public:
		output_builder(const std::filesystem::path& name, size_t buf_len = DEFAULT_STREAM_BUFFER_SIZE);

		// 返回普通文件输出类
		virtual output_t build();

		// 更改写入文件
		virtual void changeName(const std::filesystem::path& name);
	private:
		// 文件名
		std::filesystem::path _name;
		// 自定义缓冲区大小
		size_t _buf_size;
	};

	// 实例化次级建造者类
	template<>
	class output_builder<roll_file_output> : public builder_base
	{
	public:
		output_builder(const std::filesystem::path& name_base, size_t single_file_size, size_t buf_len = DEFAULT_STREAM_BUFFER_SIZE);

		// 返回滚动文件输出类
		virtual output_t build();

		// 更改滚动文件基本名
		virtual void changeName(const std::filesystem::path& name);
	private:
		// 滚动文件基本名
		std::filesystem::path _name_base;
		// 当前单位文件大小
		size_t _single_file_size;
		// 自定义缓冲区大小
		size_t _buf_size;
	};

	// 建造者类
	class output_arr_builder
	{
	public:
		// 添加次级建造者
		template<typename T, typename... Args>
		requires std::derived_from<T, output_base<T>>
		void addBuilder(Args&&... args)
		{
			_builder_arr.emplace_back(std::make_unique<output_builder<T>>(output_builder<T>{ std::forward<Args>(args)... }));
		}

		// 生成输出方式集合
		std::vector<output_t> build();

		// 更换对应位次级建造者文件名
		void changeName(size_t index, const std::filesystem::path& name);
	private:
		// 次级建造者基类指针集合
		std::vector<std::unique_ptr<builder_base>> _builder_arr;
	};
}